- Google-Search-MCP-Server
- MCP Documents
# Comprehensive Model Context Protocol (MCP) Implementation Guide
## Introduction to MCP
The Model Context Protocol (MCP) is an open protocol that standardizes how applications provide context to LLMs. Think of MCP like a USB-C port for AI applications - just as USB-C provides a standardized way to connect your devices to various peripherals and accessories, MCP provides a standardized way to connect AI models to different data sources and tools.
### What is MCP?
MCP helps you build agents and complex workflows on top of LLMs. LLMs frequently need to integrate with data and tools, and MCP provides:
- A standardized way to expose data through Resources
- Executable functionality through Tools
- Reusable interaction patterns through Prompts
- A client-server architecture where a host application can connect to multiple servers
### Core Architecture Components
The MCP architecture follows a client-server model with these key components:
1. **Host Applications**: Applications like Claude Desktop, VS Code, or other AI tools that want to access external data and tools
2. **MCP Clients**: Protocol clients that establish and maintain connections with MCP servers, handling capabilities discovery and communication
3. **MCP Servers**: Lightweight programs that expose three types of capabilities:
- **Tools**: Functions that can be called by the LLM to perform actions
- **Resources**: Data sources that provide context to the LLM
- **Prompts**: Reusable templates for LLM interactions
4. **Transport Layer**: Supports two primary mechanisms:
- **stdio (stdin/stdout)**: For local communication when clients and servers run on the same machine
- **HTTP with Server-Sent Events (SSE)**: For remote communication over networks
## MCP Protocol Details
### Communication Model
MCP uses a client-server architecture with JSON-RPC 2.0 as its messaging format. The protocol supports two primary transport mechanisms:
1. **stdio (stdin/stdout)**: Used for local communication when clients and servers run on the same machine
2. **HTTP with Server-Sent Events (SSE)**: Used for remote communication over networks
### Core Capabilities
MCP servers can provide three main types of capabilities:
1. **Tools**: Functions that can be called by the LLM (with user approval) to perform actions
2. **Resources**: Data sources that can be read by the LLM (like file contents or API responses)
3. **Prompts**: Reusable templates for LLM interactions
## Server Implementation
The server is the component that exposes tools, resources, and prompts to the client. Let's explore implementation approaches in both Python and TypeScript.
### Python Server Implementation
Python offers a high-level SDK called `FastMCP` that simplifies server implementation, as well as a lower-level SDK for more advanced use cases.
#### Basic Server Setup with FastMCP
```python
from fastmcp import FastMCP
# Create a named server
mcp = FastMCP("MyServer")
# Define a tool using decorator syntax
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers together"""
return a + b
# Define a resource
@mcp.resource("example://data")
def get_data() -> str:
"""Provide example data as a resource"""
return "Example data content"
# Define a prompt
@mcp.prompt()
def greeting(name: str) -> str:
"""Return a personalized greeting template"""
return f"Hello {name}, how can I help you today?"
# Run the server with stdio transport
if __name__ == "__main__":
mcp.run(transport="stdio")
```
#### Advanced Python Server with Low-Level API
```python
import asyncio
import mcp.server.stdio
import mcp.types as types
from mcp.server.lowlevel import NotificationOptions, Server
from mcp.server.models import InitializationOptions
# Create a server instance
server = Server("advanced-server")
# Register handlers for protocol requests
@server.list_tools()
async def handle_list_tools() -> list[types.Tool]:
"""List available tools"""
return [
types.Tool(
name="example-tool",
description="An example tool",
inputSchema={
"type": "object",
"properties": {
"param1": {"type": "string", "description": "Parameter 1"}
},
"required": ["param1"]
}
)
]
@server.call_tool()
async def handle_call_tool(name: str, arguments: dict) -> any:
"""Handle tool calls"""
if name == "example-tool":
return f"Executed tool with argument: {arguments['param1']}"
raise ValueError(f"Unknown tool: {name}")
# Main server execution
async def main():
async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
InitializationOptions(
server_name="advanced-server",
server_version="0.1.0",
capabilities=server.get_capabilities(
notification_options=NotificationOptions(),
experimental_capabilities={},
),
),
)
if __name__ == "__main__":
asyncio.run(main())
```
### TypeScript Server Implementation
TypeScript provides a flexible SDK for MCP server implementation.
#### Basic TypeScript Server Setup
```typescript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
// Create a server instance
const server = new McpServer({
name: "typescript-server",
version: "1.0.0"
});
// Define a tool
server.setRequestHandler(
{ jsonrpc: "2.0", method: "tools/list" },
async () => ({
tools: [
{
name: "multiply",
description: "Multiply two numbers",
inputSchema: {
type: "object",
properties: {
a: { type: "number", description: "First number" },
b: { type: "number", description: "Second number" }
},
required: ["a", "b"]
}
}
]
})
);
// Handle tool calls
server.setRequestHandler(
{ jsonrpc: "2.0", method: "tools/call" },
async (request) => {
const { name, arguments: args } = request.params;
if (name === "multiply") {
const result = args.a * args.b;
return { result };
}
throw new Error(`Unknown tool: ${name}`);
}
);
// Connect to stdio transport and start the server
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Server running on stdio");
}
main().catch((error) => {
console.error("Fatal error:", error);
process.exit(1);
});
```
## Client Implementation
MCP clients establish connections with servers, discover their capabilities, and relay them to the LLM. Here's how to implement clients in both Python and TypeScript.
### Python Client Implementation
#### Basic Python Client
```python
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def main():
# Define server parameters
server_params = StdioServerParameters(
command="python", # Command to run the server
args=["server.py"] # Arguments to pass to the command
)
# Connect to the server
async with stdio_client(server_params) as (read, write):
# Create a client session
async with ClientSession(read, write) as session:
# Initialize the session
await session.initialize()
# List available tools
tools_response = await session.list_tools()
print(f"Available tools: {[tool.name for tool in tools_response.tools]}")
# Call a tool
result = await session.call_tool("add", {"a": 5, "b": 3})
print(f"5 + 3 = {result.result}")
if __name__ == "__main__":
asyncio.run(main())
```
#### Integrating with Claude API
```python
import asyncio
import os
from typing import Optional, List
from contextlib import AsyncExitStack
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from anthropic import Anthropic
class MCPClaudeClient:
def __init__(self):
self.session: Optional[ClientSession] = None
self.exit_stack = AsyncExitStack()
self.anthropic = Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))
self.tools = []
async def connect_to_server(self, server_script_path):
"""Connect to an MCP server"""
server_params = StdioServerParameters(
command="python",
args=[server_script_path]
)
read, write = await self.exit_stack.enter_async_context(stdio_client(server_params))
self.session = await self.exit_stack.enter_async_context(ClientSession(read, write))
# Initialize session
await self.session.initialize()
# Discover tools
tools_response = await self.session.list_tools()
self.tools = tools_response.tools
print(f"Connected to MCP server with {len(self.tools)} tools available")
async def process_with_claude(self, user_message):
"""Process user message with Claude using MCP tools"""
if not self.session:
raise RuntimeError("No active MCP session")
# Convert MCP tools to Claude's tool format
claude_tools = []
for tool in self.tools:
claude_tools.append({
"name": tool.name,
"description": tool.description,
"input_schema": tool.parameters
})
# Send to Claude with tools
response = self.anthropic.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=1000,
messages=[{"role": "user", "content": user_message}],
tools=claude_tools
)
# Process Claude's response
for content in response.content:
if content.type == "tool_use":
# Claude wants to use a tool
tool_name = content.name
tool_args = content.input
print(f"Claude is calling tool: {tool_name}")
# Call the tool via MCP
tool_result = await self.session.call_tool(tool_name, tool_args)
# Send the result back to Claude
follow_up = self.anthropic.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=1000,
messages=[
{"role": "user", "content": user_message},
{"role": "assistant", "content": response.content},
{"role": "tool", "name": tool_name, "content": str(tool_result.result)}
]
)
return follow_up
return response
async def cleanup(self):
"""Clean up resources"""
await self.exit_stack.aclose()
async def main():
client = MCPClaudeClient()
try:
await client.connect_to_server("path/to/server.py")
response = await client.process_with_claude("Calculate 5 + 3")
print(response)
finally:
await client.cleanup()
if __name__ == "__main__":
asyncio.run(main())
```
### TypeScript Client Implementation
#### Basic TypeScript Client
```typescript
import { McpClient } from "@modelcontextprotocol/sdk/client/mcp.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
async function main() {
// Create a transport
const transport = new StdioClientTransport({
command: "node",
args: ["server.js"]
});
// Create client and connect
const client = new McpClient();
await client.connect(transport);
// Create a session
const session = await client.createSession();
// Initialize session
await session.initialize();
// List available tools
const { tools } = await session.listTools();
console.log("Available tools:", tools.map(tool => tool.name));
// Call a tool
const result = await session.callTool("multiply", { a: 5, b: 3 });
console.log("5 * 3 =", result.result);
// Clean up
await client.disconnect();
}
main().catch(console.error);
```
## Python vs TypeScript: A Comparison
When choosing between Python and TypeScript for MCP implementation, there are several factors to consider:
### Strengths of Python for MCP
1. **High-Level Abstractions**: Python's `FastMCP` provides a very clean, decorator-based API that makes creating servers intuitive
2. **Type Annotations**: Modern Python's type hints work well with MCP's schema requirements
3. **Async Support**: Python's asyncio integrates well with the asynchronous nature of MCP
4. **AI Ecosystem**: Python has a strong ecosystem for AI/ML, making it easier to integrate with other AI libraries
5. **Claude Integration**: The official Anthropic Python SDK integrates well with MCP
### Strengths of TypeScript for MCP
1. **JSON Native**: TypeScript's JavaScript roots make it natural for working with JSON-RPC
2. **Web Integration**: Better for building web-based clients or servers (especially with SSE transport)
3. **Type System**: More mature type system with interfaces and generics for protocol validation
4. **NPX Execution**: TypeScript servers can be easily run with `npx` without installation
5. **Most Official Examples**: More official example implementations use TypeScript
### Development Experience Comparison
| Aspect | Python | TypeScript |
|--------|--------|------------|
| Setup Complexity | Simpler with FastMCP | More boilerplate code |
| Typing Experience | Good, but less strict | Excellent, more strict |
| Debugging | Excellent Python tooling | Good browser/Node tooling |
| Deployment | Requires Python runtime | Requires Node.js runtime |
| Learning Curve | Gentle with FastMCP | Steeper with lower-level API |
### Performance Considerations
For most MCP implementations, performance differences between Python and TypeScript will be negligible, as MCP operations are typically I/O bound rather than CPU bound. The choice should be based more on your team's expertise and integration requirements.
## Windows-Specific Considerations
Implementing MCP on Windows platforms requires attention to specific issues, especially when using stdio transport:
### Line Ending Handling
Windows uses CRLF (`\r\n`) for line endings while Unix systems use LF (`\n`). This can cause issues with stdio transport if not handled correctly.
#### Python Solution
```python
import sys
import os
# Force binary mode for stdin/stdout on Windows
if sys.platform == 'win32':
import msvcrt
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
```
#### TypeScript Solution
```typescript
if (process.platform === 'win32') {
process.stdin.setEncoding('binary');
process.stdout.setDefaultEncoding('binary');
}
```
### Path Separators
Windows uses backslashes (`\`) in file paths, while MCP server commands often use forward slashes (`/`). Most MCP SDKs handle this automatically, but custom implementations need to be aware of this difference.
### Executable Extensions
Windows commands typically require `.exe` extensions, and JavaScript/TypeScript scripts may require `.cmd` or `.bat` wrappers to run properly. The SDKs handle this, but custom implementations should consider it.
## Best Practices for MCP Implementation
### Security Best Practices
1. **User Consent**: Always obtain explicit user consent before executing tools
2. **Input Validation**: Validate all inputs at both the client and server levels
3. **Least Privilege**: Servers should operate with the minimum required permissions
4. **Secure Protocols**: Use HTTPS for remote connections (SSE transport)
5. **Authentication**: Implement proper authentication for remote servers
### Error Handling
1. **Graceful Degradation**: Handle server unavailability gracefully
2. **Timeouts**: Implement reasonable timeouts for operations
3. **Retry Logic**: Add retry mechanisms for transient failures
4. **Descriptive Errors**: Provide clear error messages for debugging
### Performance Optimization
1. **Connection Pooling**: Reuse connections where possible
2. **Caching**: Cache capabilities and frequently used resources
3. **Batching**: Batch multiple requests when appropriate
4. **Compression**: Use compression for large resource transfers
## Comprehensive Example: Building a Complete MCP Ecosystem
Let's put everything together with a complete example that includes:
- A Python-based MCP server with multiple tools
- A TypeScript-based MCP client
- Integration with Claude via the Anthropic API
### Project Structure
```
mcp-ecosystem/
├── server/
│ ├── server.py # Python MCP server
│ └── requirements.txt # Python dependencies
├── client/
│ ├── package.json # Node.js package definition
│ ├── tsconfig.json # TypeScript configuration
│ └── src/
│ └── client.ts # TypeScript MCP client
└── README.md # Project documentation
```
## Conclusion
The Model Context Protocol (MCP) provides a powerful standardized way to integrate LLMs with external tools and data sources. Both Python and TypeScript offer robust SDKs for implementing MCP clients and servers.
Python's strengths lie in its simplicity, high-level abstractions, and excellent integration with the AI ecosystem. TypeScript shines with its native JSON handling, strong type system, and web integration capabilities.
The choice between Python and TypeScript should be based on your specific requirements, team expertise, and the broader ecosystem you're integrating with. For AI-focused teams already working with Python, the Python SDK offers the smoothest experience. For web developers or teams building web-based AI applications, TypeScript might be the better choice.
## Additional Resources
- [Official MCP Documentation](https://modelcontextprotocol.io/docs)
- [MCP Specification](https://spec.modelcontextprotocol.io/specification/2025-03-26/)
- [TypeScript SDK Repository](https://github.com/modelcontextprotocol/typescript-sdk)
- [Python SDK Repository](https://github.com/modelcontextprotocol/python-sdk)
- [Example MCP Servers](https://github.com/modelcontextprotocol/servers)